//
//  IAPHelper.m
//
//  Original Created by Ray Wenderlich on 2/28/11.
//  Created by zhuzj on 7/9/12.
//  Copyright 2011 Ray Wenderlich. All rights reserved.
//

#import "IAPHelper.h"

@interface IAPHelper()

@property (nonatomic, copy) IAPProductsResponseBlock requestProductsBlock;
@property (nonatomic, copy) IAPbuyProductCompleteResponseBlock buyProductCompleteBlock;
@property (nonatomic, copy) IAPToCheckReceiptBlock toCheckReceiptBlock;//票据校验逻辑实现
@property (nonatomic, copy) IAPResoreProductsCompleteResponseBlock restoreCompletedBlock;
@property (nonatomic, copy) IAPCheckReceiptCompleteResponseBlock checkReceiptCompleteBlock;
@property (nonatomic, copy) IAPTransactionStateBlock transactionStateBlock;

@property (nonatomic, strong) NSMutableData* receiptRequestData;

@property (nonatomic, assign) BOOL hasAddTransactionObserver;

@end

@implementation IAPHelper

- (instancetype)init {
    if ((self = [super init])) {
        [self addTransactionObserver:nil toCheckReceiptBlock:nil onCompletion:nil];
    }
    return self;
}

- (void)dealloc
{
    [self removeTransactionObserver];
    NSLog(@"%@##%@",NSStringFromClass([self class]),NSStringFromSelector(_cmd));
}

#pragma mark 添加和移除购买监听
//建议app启动时就调用
- (void)addTransactionObserver:(IAPTransactionStateBlock)transactionState
           toCheckReceiptBlock:(IAPToCheckReceiptBlock)toCheckReceiptBlock
                  onCompletion:(IAPbuyProductCompleteResponseBlock)completion{
    
    if (transactionState || toCheckReceiptBlock || completion) {
        [self resetBlocks];
        self.buyProductCompleteBlock = completion;
        self.transactionStateBlock = transactionState;
        self.toCheckReceiptBlock = toCheckReceiptBlock;
    }
    
    if (self.hasAddTransactionObserver) {
        return;
    }
    if ([SKPaymentQueue defaultQueue]) {
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];
        self.hasAddTransactionObserver = YES;
    }
    
}

- (void)removeTransactionObserver {
    if ([SKPaymentQueue defaultQueue]) {
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    }
}

- (void)resetBlocks {
    self.buyProductCompleteBlock = nil;
    self.restoreCompletedBlock = nil;
    self.toCheckReceiptBlock = nil;
    self.transactionStateBlock = nil;
}

#pragma mark 用productIdentifiers向苹果服务器请求商品信息 (SKProductsRequest)
- (void)requestProductsWithProductIdentifiers:(NSSet *)productIdentifiers
                                   completion:(IAPProductsResponseBlock)completion {
    
    self.productIdentifiers = productIdentifiers;
    self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:self.productIdentifiers];
    self.request.delegate = self;
    self.requestProductsBlock = completion;
    
    [self.request start];
    
}

#pragma mark 客户发起购买
///判断用户是否允许app内购
- (BOOL)canMakePayments {
    return SKPaymentQueue.canMakePayments;
}

///客户发起购买
- (void)buyProductWithSKProduct:(SKProduct *)product
               transactionState:(IAPTransactionStateBlock)transactionState
            toCheckReceiptBlock:(IAPToCheckReceiptBlock)toCheckReceiptBlock
                   onCompletion:(IAPbuyProductCompleteResponseBlock)completion{
    
    //clear it
    [self resetBlocks];
    
    self.buyProductCompleteBlock = completion;
    self.transactionStateBlock = transactionState;
    self.toCheckReceiptBlock = toCheckReceiptBlock;
    
    SKPayment *payment = [SKPayment paymentWithProduct:product];
    
    if ([SKPaymentQueue defaultQueue]) {
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
    
}

#pragma mark 从用户的购买历史记录中恢复的 客户的应完成交易（基本不会调用，因为用不到，在addTransactionObserver的监听实现了该逻辑的功能restore）
- (void)restoreProductsTransactionState:(IAPTransactionStateBlock)transactionState
                             completion:(IAPResoreProductsCompleteResponseBlock)completion
                    toCheckReceiptBlock:(IAPToCheckReceiptBlock)toCheckReceiptBlock{
    
    //clear it
    [self resetBlocks];
    
    self.restoreCompletedBlock = completion;
    self.transactionStateBlock = transactionState;
    self.toCheckReceiptBlock = toCheckReceiptBlock;
    
    if ([SKPaymentQueue defaultQueue]) {
        [[SKPaymentQueue defaultQueue] restoreCompletedTransactions];
    }
}

#pragma mark SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    
    self.products = response.products;
    self.request = nil;
    
    !self.requestProductsBlock ? : self.requestProductsBlock(request, response, nil);
    
}

- (void)request:(SKRequest *)request didFailWithError:(NSError *)error {
    !self.requestProductsBlock ? : self.requestProductsBlock((SKProductsRequest *)request, nil, error);
}

#pragma mark 处理客户交易（根据交易状态 3种 具体实现逻辑）
- (void)recordTransaction:(SKPaymentTransaction *)transaction {
    // TODO: Record the transaction on the server side...
    
    !self.transactionStateBlock ? : self.transactionStateBlock(transaction);
    
    //交易操作完成处理
    if (transaction.transactionState == SKPaymentTransactionStatePurchased ||
        transaction.transactionState == SKPaymentTransactionStateRestored ||
        transaction.transactionState == SKPaymentTransactionStateFailed ){
        
        //1.交易失败
        if(transaction.transactionState == SKPaymentTransactionStateFailed){
            
            [self finishTransaction:transaction];
            return;
        }
        
        //2.交易结果(需要票据验证)
        // 发送网络请求,到开发者自己的服务器进行验证
        //...
        
        //TODO: 下面代码需要在交易票据成功后的处理（一般是后台拿票据去苹果服务器校验）
        //NSURL *receiptUrl = NSBundle.mainBundle.appStoreReceiptURL;//将AppStore返回的票据（receipt）发送到服务器进行校验
        !self.toCheckReceiptBlock ? : self.toCheckReceiptBlock(transaction);
        
        //放到toCheckReceiptBlock的实现中处理
        //        BOOL checkReceipt = YES;//-z for test 关闭交易
        //        if (checkReceipt) {
        //            [self finishTransaction:transaction];
        //        }
        
    }
}

#pragma mark finishTransaction (结束交易)
- (void)finishTransaction:(SKPaymentTransaction *)transaction {
    if ([SKPaymentQueue defaultQueue]) {
        [[SKPaymentQueue defaultQueue] finishTransaction: transaction];
        
        !self.buyProductCompleteBlock ? : self.buyProductCompleteBlock(transaction);
    }
}

#pragma mark SKPaymentTransactionObserver
- (void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray *)transactions
{
    for (SKPaymentTransaction *transaction in transactions)
    {
        [self print:transaction transactions:transactions];
        [self completeTransaction:transaction];
    }
}

#pragma mark 处理客户交易（根据交易状态）
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
    
    switch (transaction.transactionState){
        case SKPaymentTransactionStatePurchasing://交易正在进行中
        {
            [self recordTransaction:transaction];
        }
            break;
        case SKPaymentTransactionStatePurchased://正常流程的 客户的应完成交易
        {
            [self recordTransaction:transaction];
        }
            break;
        case SKPaymentTransactionStateRestored://从用户的购买历史记录中恢复的 客户的应完成交易
        {
            [self recordTransaction:transaction];
        }
            break;
        case SKPaymentTransactionStateFailed://交易失败
        {
            [self recordTransaction:transaction];
        }
            break;
        default:
            break;
    }
}

- (void)paymentQueue:(SKPaymentQueue *)queue restoreCompletedTransactionsFailedWithError:(NSError *)error {
    NSLog(@"Transaction error: %@ %ld", error.localizedDescription,(long)error.code);
    !self.restoreCompletedBlock ? : self.restoreCompletedBlock(queue,error);
}

- (void)paymentQueueRestoreCompletedTransactionsFinished:(SKPaymentQueue *)queue {
    
    for (SKPaymentTransaction *transaction in queue.transactions)
    {
        switch (transaction.transactionState)
        {
            case SKPaymentTransactionStateRestored:
            {
                [self recordTransaction: transaction];
            }
            default:
                break;
        }
    }
    
    !self.restoreCompletedBlock ? : self.restoreCompletedBlock(queue,nil);
    
}

#pragma mark 票据（Receipt）校验【强烈建议放到后端】
- (void)checkReceipt:(NSData*)receiptData onCompletion:(IAPCheckReceiptCompleteResponseBlock)completion
{
    [self checkReceipt:receiptData andSharedSecret:nil onCompletion:completion];
}

- (void)checkReceipt:(NSData*)receiptData andSharedSecret:(NSString*)secretKey onCompletion:(IAPCheckReceiptCompleteResponseBlock)completion
{
    
    self.checkReceiptCompleteBlock = completion;
    
    NSMutableDictionary *params = [NSMutableDictionary new];
    [params setValue:receiptData.base64EncodedString forKey:@"receipt-data"];
    if (secretKey) {
        [params setValue:secretKey forKey:@"password"];
    }
    
    NSData *jsonData = params.modelToJSONData;
    
    NSURL *requestURL = nil;
    if(self.production)
    {
        requestURL = [NSURL URLWithString:@"https://buy.itunes.apple.com/verifyReceipt"];
    }
    else {
        requestURL = [NSURL URLWithString:@"https://sandbox.itunes.apple.com/verifyReceipt"];
    }
    
    NSMutableURLRequest *req = [[NSMutableURLRequest alloc] initWithURL:requestURL];
    [req setHTTPMethod:@"POST"];
    [req setHTTPBody:jsonData];
    
    NSURLSessionDataTask * task = [NSURLSession.sharedSession dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
        if (error) {
            !self.checkReceiptCompleteBlock ? : self.checkReceiptCompleteBlock(nil,error);
            return;
        }
        
        !self.checkReceiptCompleteBlock ? : self.checkReceiptCompleteBlock(data.jsonValueDecoded,nil);
        
    }];
    [task resume];
}

#pragma mark tool
- (NSString *)getLocalePrice:(SKProduct *)product {
    if (product) {
        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
        [formatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
        [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
        [formatter setLocale:product.priceLocale];
        
        return [formatter stringFromNumber:product.price];
    }
    return @"";
}

- (void)print:(SKPaymentTransaction *)transaction transactions:(NSArray *)transactions {
    
    NSMutableString *recordStr = [NSMutableString stringWithFormat:@"交易记录##总条数:%lu##transactionIdentifier:%@##transactionDate:%@##transactionState:%@",(unsigned long)transactions.count,transaction.transactionIdentifier, transaction.transactionDate,[self transactionStateStr:transaction.transactionState]];
    if (transaction.transactionState == SKPaymentTransactionStateRestored) {
        transaction = transaction.originalTransaction;
        NSMutableString *originalRecordStr = [NSMutableString stringWithFormat:@"该交易记录的原始交易##总条数:%lu##transactionIdentifier:%@##transactionDate:%@##transactionState:%@",(unsigned long)transactions.count,transaction.transactionIdentifier, transaction.transactionDate,[self transactionStateStr:transaction.transactionState]];
        [recordStr appendString:originalRecordStr];
    }
    NSLog(@"%@",recordStr);
    
}

- (NSString *)transactionStateStr:(SKPaymentTransactionState)transactionState {
    
    switch (transactionState) {
        case SKPaymentTransactionStatePurchasing:
        {
            return @"SKPaymentTransactionStatePurchasing";
        }
            break;
        case SKPaymentTransactionStatePurchased:
        {
            return @"SKPaymentTransactionStatePurchased";
        }
            break;
        case SKPaymentTransactionStateFailed:
        {
            return @"SKPaymentTransactionStateFailed";
        }
            break;
        case SKPaymentTransactionStateRestored:
        {
            return @"SKPaymentTransactionStateRestored";
        }
            break;
        case SKPaymentTransactionStateDeferred:
        {
            return @"SKPaymentTransactionStateDeferred";
        }
            break;
        default:
            break;
    }
}

@end
